home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.05 May 90 / Language Translation Code / Hyphen Files / Hyphen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-17  |  10.0 KB  |  466 lines  |  [TEXT/MPS ]

  1. //////////////////////////////////////////////////////////////////
  2. //    
  3. //        Hyphen.c
  4. //        --------
  5. //        Skeleton MPW Hyphen tool
  6. //    
  7. //////////////////////////////////////////////////////////////////
  8.     
  9. #pragma load "managers"
  10.     
  11. //////////////////////////////////////////////////////////////////
  12. //    
  13. //        Constants and Macros
  14. //    
  15. //////////////////////////////////////////////////////////////////
  16.     
  17. #define nil                    0
  18.     
  19. #define stdinfd            0
  20. #define stdoutfd            1
  21. #define stderrfd            2
  22.     
  23. #define stdunit(x)        ((x >= stdinfd) && (x <= stderrfd))
  24. #define notstdunit(x)    (x > stderrfd)
  25.  
  26. #define nombuffsize        1024
  27. #define truebuffsize        1200
  28.     
  29. //////////////////////////////////////////////////////////////////
  30. //    
  31. //        Types
  32. //    
  33. //////////////////////////////////////////////////////////////////
  34.     
  35. typedef enum {false, true} logical;
  36. typedef enum {nocode, pascalcode, ccode} codetype;
  37.     
  38. //////////////////////////////////////////////////////////////////
  39. //    
  40. //        Globals
  41. //    
  42. //////////////////////////////////////////////////////////////////
  43.     
  44. //////////////////////////////////////////////////////////////////
  45. //    
  46. //        Prototypes
  47. //    
  48. //////////////////////////////////////////////////////////////////
  49.     
  50.     void initmac();
  51.     int openoutput(char *thename, int output);
  52.     int readinput(int input, Handle inbuffer, int buffersize);
  53.     int filter(char *inbuffer, int buffersize, int output, codetype language);
  54.     int writeoutput(int output, char *outbuffer, int buffersize);
  55.     
  56. //////////////////////////////////////////////////////////////////
  57. //
  58. //        main
  59. //        ----
  60. //        the "main" routine reads and interprets the command line,
  61. //        concatenates input files into an input buffer, opens the
  62. //        output file, and calls the "filter" routine to write the
  63. //        output.
  64. //
  65. //////////////////////////////////////////////////////////////////
  66.     
  67. int main(int argc, char *argv[])
  68.     {
  69.     
  70.     int                index;
  71.     int                input;
  72.     int                output;
  73.     codetype            language;
  74.     Handle            inbuffer;
  75.     int                buffersize;
  76.     char                *thetail;
  77.     
  78.     initmac();
  79.     
  80. //    "input" is the fd of the input file, initially stdin
  81. //    "output" is the fd of the output file, initially stdout
  82. //    "language" is the language to parse, initially unknown
  83.     
  84.     input = stdinfd;
  85.     output = stdoutfd;
  86.     language = nocode;
  87.     
  88. //    "inbuffer" is the input buffer,
  89. //        initially empty but able to grow
  90. //    "buffersize" is the size of "inbuffer"
  91.     
  92.     inbuffer = NewHandle(0);
  93.     buffersize = 0;
  94.     
  95. //    command line interpreter: loop through command options
  96.     
  97.     for (index = 1; index < argc; index++)
  98.         {
  99.         
  100.         if (argv[index][0] == '-')
  101.             {
  102.             
  103.             switch (argv[index][1])
  104.                 {
  105.     
  106. //    "-p" and "-c" options set language type;
  107. //        these override any previous setting
  108.                 
  109.                 case 'P':
  110.                 case 'p':
  111.                     language = pascalcode;
  112.                     break;
  113.                 
  114.                 case 'C':
  115.                 case 'c':
  116.                     language = ccode;
  117.                     break;
  118.                 
  119.                 case 'O':
  120.                 case 'o':
  121.                     output = openoutput(argv[++index], output);
  122.                     if (output < 0)
  123.                         {
  124.                         fprintf(stderr, "Error - Unable to open "
  125.                                         "output file %s!\n", argv[index]);
  126.                         exit(2);
  127.                         }
  128.                     break;
  129.                 
  130.                 default:
  131.                     fprintf(stderr, "Error - Unknown option %s\n", argv[index]);
  132.                     exit(2);
  133.                     break;
  134.                 
  135.                 }
  136.             
  137.             }
  138.         else
  139.             {
  140.     
  141. //    if "language" has not changed since initialization,
  142. //        set "language" according to file name (the
  143. //        first input file thus determines language type)
  144.             
  145.             if (language == nocode)
  146.                 {
  147.                 thetail = argv[index] + strlen(argv[index]) - 2;
  148.                 if (strcmp(thetail, ".p") == 0)
  149.                     language = pascalcode;
  150.                 else if (strcmp(thetail, ".c") == 0)
  151.                     language = ccode;
  152.                 }
  153.     
  154. //    open the input file (after this step, "input"
  155. //        will NOT contain a standard unit number)
  156. //        and read it into the input buffer
  157.             
  158.             input = open(argv[index], O_RDONLY);
  159.             if (input < 0)
  160.                 {
  161.                 fprintf(stderr, "Error - Unable to open "
  162.                                 "input file %s!\n", argv[index]);
  163.                 exit(2);
  164.                 }
  165.             
  166.             buffersize = readinput(input, inbuffer, buffersize);
  167.             if (buffersize < 0)
  168.                 {
  169.                 fprintf(stderr, "Error - Reading from %s!\n", argv[index]);
  170.                 exit(2);
  171.                 }
  172.             
  173.             close(input);
  174.             
  175.             }
  176.         
  177.         }
  178.     
  179. //    if "input" is still a standard unit number, then no
  180. //        input file was opened, and input must be from
  181. //        standard input
  182.     
  183.     if (stdunit(input))
  184.         {
  185.         buffersize = readinput(input, inbuffer, buffersize);
  186.         if (buffersize < 0)
  187.             {
  188.             fprintf(stderr, "Error - Reading from standard input!\n");
  189.             exit(2);
  190.             }
  191.         }
  192.     
  193. //    if "language" is still unknown, set it to Pascal
  194.     
  195.     if (language == nocode)
  196.         language = pascalcode;
  197.     
  198. //    the routine "filter" does the real work of the program
  199.     
  200.     HLock(inbuffer);
  201.     filter(*inbuffer, buffersize, output, language);
  202.     HUnlock(inbuffer);
  203.     
  204. //    wrapup:  close "output" first if the program opened it
  205.     
  206.     DisposHandle(inbuffer);
  207.     
  208.     if (notstdunit(output))
  209.         close(output);
  210.     
  211.     exit(0);
  212.     
  213.     }
  214.     
  215. //////////////////////////////////////////////////////////////////
  216. //
  217. //        initmac
  218. //        -------
  219. //        initialize any necessary managers and whatnot.
  220. //
  221. //////////////////////////////////////////////////////////////////
  222.     
  223. void initmac()
  224.     {
  225.     
  226.     InitGraf((Ptr)&qd.thePort);
  227.     SetFScaleDisable(true);
  228.     
  229.     InitCursorCtl(nil);
  230.     
  231.     }
  232.     
  233. //////////////////////////////////////////////////////////////////
  234. //
  235. //        openoutput
  236. //        ----------
  237. //        open the output file.  returns the fd or, if an error
  238. //        occurs, the error flag.
  239. //
  240. //////////////////////////////////////////////////////////////////
  241.     
  242. int openoutput(char *thename, int output)
  243.     {
  244.     
  245.     FInfo                theinfo;
  246.     
  247. //    if "output" is not a standard unit, then an output
  248. //        file must have already be open
  249.     
  250.     if (notstdunit(output))
  251.         {
  252.         fprintf(stderr, "Warning - additional output "
  253.                         "file %s ignored!\n", thename);
  254.         return(output);
  255.         }
  256.  
  257. //    open the output file for writing (O_WRONLY),
  258. //        creating it if necessary (O_CREAT) and
  259. //        zeroing it otherwise (O_TRUNC)
  260.     
  261.     output = open(thename, O_WRONLY + O_CREAT + O_TRUNC);
  262.     if (output < 0)
  263.         return(output);
  264.  
  265. //    if the file was created by "open", it will be
  266. //        untyped, so set the type to TEXT and MPS
  267.     
  268.     if (getfinfo(thename, 0, &theinfo))
  269.         {
  270.         fprintf(stderr, "Warning - unable to get info for "
  271.                         "output file %s!\n", thename);
  272.         return(output);
  273.         }
  274.     
  275.     theinfo.fdType = 'TEXT';
  276.     theinfo.fdCreator = 'MPS ';
  277.     
  278.     if (setfinfo(thename, 0, &theinfo))
  279.         fprintf(stderr, "Warning - unable to set info for "
  280.                         "output file %s!\n", thename);
  281.     
  282.     return(output);
  283.     
  284.     }
  285.     
  286. //////////////////////////////////////////////////////////////////
  287. //
  288. //        readinput
  289. //        ---------
  290. //        this routine appends an input file to the input buffer and
  291. //        returns the new size of the buffer or, if a read error
  292. //        occurs, the error flag.
  293. //
  294. //////////////////////////////////////////////////////////////////
  295.     
  296. int readinput(int input, Handle inbuffer, int buffersize)
  297.     {
  298.     
  299.     int                readsize;
  300.     
  301.     SetHandleSize(inbuffer, buffersize + 1024);
  302.     HLock(inbuffer);
  303.     
  304.     while ((readsize = read(input, *inbuffer + buffersize, 1024)) > 0)
  305.         {
  306.         buffersize += readsize;
  307.         HUnlock(inbuffer);
  308.         SetHandleSize(inbuffer, buffersize + 1024);
  309.         HLock(inbuffer);
  310.         }
  311.     
  312.     if (readsize < 0)
  313.         return(readsize);
  314.     
  315.     HUnlock(inbuffer);
  316.     SetHandleSize(inbuffer, buffersize + 1024);
  317.     
  318.     return(buffersize);
  319.     
  320.     }
  321.     
  322. //////////////////////////////////////////////////////////////////
  323. //
  324. //        filter
  325. //        ------
  326. //        this routine does the main work of the program.
  327. //
  328. //////////////////////////////////////////////////////////////////
  329.     
  330. int filter(char *inbuffer, int buffersize, int output, codetype language)
  331.     {
  332.     
  333.     int                inposition;
  334.     int                outposition;
  335.     Handle            thehandle;
  336.     char                *classtable;
  337.     char                *statetable;
  338.     char                outbuffer[truebuffsize];
  339.     int                thestate;
  340.     unsigned char    thechar;
  341.     int                theclass;
  342.     int                newstate;
  343.     int                writesize;
  344.     
  345. //    "inposition" keeps track of the current position in the
  346. //        input buffer, initially at the beginning
  347. //    "outposition" keeps track of the current position in the
  348. //        output buffer, initially at the beginning
  349.     
  350.     inposition = 0;
  351.     outposition = 0;
  352.     
  353. //    "classtable" is the character classification table,
  354. //        and "statetable" is set according to language
  355. //        type; note that both will be disposed of by
  356. //        CloseResFile on exit, since they're resources
  357.     
  358.     thehandle = GetResource('TABL', 1000);
  359.     HLock(thehandle);
  360.     classtable = *thehandle;
  361.     
  362.     if (language == pascalcode)
  363.         thehandle = GetResource('TABL', 1001);
  364.     else
  365.         thehandle = GetResource('TABL', 1002);
  366.     HLock(thehandle);
  367.     statetable = *thehandle;
  368.     
  369. //    start the machine in state 0
  370.     
  371.     thestate = 0;
  372.     while (inposition < buffersize)
  373.         {
  374.     
  375. //    fetch a character from the input buffer
  376.         
  377.         thechar = *(inbuffer + inposition++);
  378.     
  379. //    determine the new state
  380.         
  381.         theclass = classtable[thechar];
  382.         newstate = statetable[12 * thestate + theclass];
  383.     
  384. //    overwrite an embedded hyphen
  385.         
  386.         if ((thestate == 6) && (newstate == 5))
  387.             outposition--;
  388.     
  389. //    copy input to the output buffer
  390.         
  391.         outbuffer[outposition++] = thechar;
  392.     
  393. //    back up if necessary
  394.         
  395.         if (newstate == 0)
  396.             {
  397.             
  398.             switch (thestate)
  399.                 {
  400.                 
  401.                 case 2:
  402.                 case 5:
  403.                     inposition--;
  404.                     outposition--;
  405.                     break;
  406.                 
  407.                 case 6:
  408.                     inposition -= 2;
  409.                     outposition -= 2;
  410.                     break;
  411.                 
  412.                 }
  413.             
  414.             }
  415.     
  416. //    when the output buffer fills up, write it to output
  417.         
  418.         if ((outposition >= nombuffsize) && ((thestate != 5) || (newstate != 6)))
  419.             {
  420.             outposition = writeoutput(output, outbuffer, outposition);
  421.             if (outposition < 0)
  422.                 return(outposition);
  423.             }
  424.     
  425. //    shift to the new state
  426.         
  427.         thestate = newstate;
  428.         
  429.         }
  430.     
  431. //    write whatever is left in the buffer directly to output
  432.     
  433.     writesize = write(output, outbuffer, outposition);
  434.     return(writesize);
  435.     
  436.     }
  437.     
  438. //////////////////////////////////////////////////////////////////
  439. //
  440. //        writeoutput
  441. //        ----------
  442. //        this routine flushes the output buffer by writing
  443. //        it to the output file.  It returns the new size of the
  444. //        buffer or, if a write error occurs, the error flag.
  445. //
  446. //////////////////////////////////////////////////////////////////
  447.     
  448. int writeoutput(int output, char *outbuffer, int buffersize)
  449.     {
  450.     
  451.     int                writesize;
  452.     
  453.     writesize = write(output, outbuffer, nombuffsize);
  454.     
  455.     if (writesize < 0)
  456.         return(writesize);
  457.     
  458.     buffersize -= writesize;
  459.     BlockMove(outbuffer + writesize, outbuffer, buffersize);
  460.     
  461.     return(buffersize);
  462.     
  463.     }
  464.     
  465. //////////////////////////////////////////////////////////////////
  466.